package com.meilai.project.service.business.customer.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.meilai.project.controller.mini.dto.MiniCustomerInfoDTO;
import com.meilai.project.dto.workflow.FlowBusinessDataSuperEntity;
import com.meilai.project.dto.workflow.WorkFlowCheckDTO;
import com.meilai.project.dto.workflow.WorkFlowExtraCheckDTO;
import com.meilai.project.entity.business.customer.*;
import com.meilai.project.exception.CommonException;
import com.meilai.project.mapper.business.customer.MiniCustomerEditFlowMapper;
import com.meilai.project.service.business.customer.*;
import com.meilai.project.util.ThreadLocalUserUtil;
import com.meilai.project.util.WorkFlowUtil;
import com.meilai.project.vo.business.customer.MiniCustomerEditFlowVO;
import com.meilai.project.vo.system.UserVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author xhy
 * @since 2022-11-06
 */
@Service
public class MiniCustomerEditFlowServiceImpl extends ServiceImpl<MiniCustomerEditFlowMapper, MiniCustomerEditFlow> implements MiniCustomerEditFlowService {

    @Autowired
    private MiniCustomerEditFunnelTmpService miniCustomerEditFunnelTmpService;

    @Autowired
    private MiniCustomerEditSelectionReasonTmpService miniCustomerEditSelectionReasonTmpService;

    @Autowired
    private CustomerInfoService customerInfoService;

    @Autowired
    private CustomerFunnelService customerFunnelService;

    @Autowired
    private CustomerSelectionReasonService customerSelectionReasonService;

    @Override
    public MiniCustomerEditFlowVO getOneById(Long id) {
        MiniCustomerEditFlowVO vo = baseMapper.getOneById(id);
        vo.setFunnels(miniCustomerEditFunnelTmpService.list(Wrappers.<MiniCustomerEditFunnelTmp>lambdaQuery().eq(MiniCustomerEditFunnelTmp::getMini_customer_edit_flow_id, vo.getId())).stream().map(MiniCustomerEditFunnelTmp::getFunnel_type_id).collect(Collectors.toList()));
        vo.setSelection_reasons(miniCustomerEditSelectionReasonTmpService.list(Wrappers.<MiniCustomerEditSelectionReasonTmp>lambdaQuery().eq(MiniCustomerEditSelectionReasonTmp::getMini_customer_edit_flow_id, vo.getId())).stream().map(MiniCustomerEditSelectionReasonTmp::getSelection_reason_id).collect(Collectors.toList()));
        Long user_id = ThreadLocalUserUtil.get().getId();
        vo.setCan_check(WorkFlowUtil.canCheckData(user_id, vo));
        return vo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean save(MiniCustomerInfoDTO dto) {
        // 保存至草稿箱
        int flowResult = saveAndBegin(dto, true);
        if (flowResult != 1) {
            throw new CommonException("保存至草稿箱失败，请联系管理员！");
        } else {
            return true;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean begin(MiniCustomerInfoDTO dto) {
        // 提交
        int flowResult = saveAndBegin(dto, false);
        if (flowResult == 1) {
            // 仍在流程中
            return true;
        } else if (flowResult == 2) {
            // 无审批节点，直接结束
            return true;
        } else {
            throw new CommonException("提交失败，请联系管理员！");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean pass(WorkFlowExtraCheckDTO dto) {
        // 通过
        int flowResult = passAndBack(dto, true);
        if (flowResult == 1) {
            // 通过后仍然在流程中
            return true;
        } else if (flowResult == 2) {
            // 审核后流程结束
            // 更新客户信息
            MiniCustomerEditFlow miniCustomerEditFlow = this.getById(dto.getId());
            CustomerInfo customerInfo = new CustomerInfo();
            BeanUtils.copyProperties(miniCustomerEditFlow, customerInfo);
            customerInfo.setId(miniCustomerEditFlow.getCustomer_id());
            customerInfoService.updateById(customerInfo);
            // 更新客户子表
            customerFunnelService.remove(Wrappers.<CustomerFunnel>lambdaQuery().eq(CustomerFunnel::getCustomer_id, customerInfo.getId()));
            customerSelectionReasonService.remove(Wrappers.<CustomerSelectionReason>lambdaQuery().eq(CustomerSelectionReason::getCustomer_id, customerInfo.getId()));
            List<MiniCustomerEditFunnelTmp> miniCustomerEditFunnelTmpList = miniCustomerEditFunnelTmpService.list(Wrappers.<MiniCustomerEditFunnelTmp>lambdaQuery().eq(MiniCustomerEditFunnelTmp::getMini_customer_edit_flow_id, dto.getId()));
            List<MiniCustomerEditSelectionReasonTmp> miniCustomerEditSelectionReasonTmpList = miniCustomerEditSelectionReasonTmpService.list(Wrappers.<MiniCustomerEditSelectionReasonTmp>lambdaQuery().eq(MiniCustomerEditSelectionReasonTmp::getMini_customer_edit_flow_id, dto.getId()));
            customerFunnelService.saveBatch(miniCustomerEditFunnelTmpList.stream().map(item -> {
                CustomerFunnel customerFunnel = new CustomerFunnel();
                customerFunnel.setFunnel_type_id(item.getFunnel_type_id());
                customerFunnel.setCustomer_id(customerInfo.getId());
                return customerFunnel;
            }).collect(Collectors.toList()));
            customerSelectionReasonService.saveBatch(miniCustomerEditSelectionReasonTmpList.stream().map(item -> {
                CustomerSelectionReason customerSelectionReason = new CustomerSelectionReason();
                customerSelectionReason.setSelection_reason_id(item.getSelection_reason_id());
                customerSelectionReason.setCustomer_id(customerInfo.getId());
                return customerSelectionReason;
            }).collect(Collectors.toList()));
            return true;
        } else {
            throw new CommonException("通过失败，请联系管理员！");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean returnBack(WorkFlowExtraCheckDTO dto) {
        // 驳回
        int flowResult = passAndBack(dto, false);
        if (flowResult != 1) throw new CommonException("驳回失败，请联系管理员！");
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean delete(Long id) {
        int flowResult = deleteAndActualDel(id, false);
        if (flowResult != 1) throw new CommonException("删除失败，请联系管理员！");
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean actualDelete(Long id) {
        int flowResult = deleteAndActualDel(id, true);
        if (flowResult != 1) throw new CommonException("彻底删除失败，请联系管理员！");
        return true;
    }

    private int saveAndBegin(MiniCustomerInfoDTO dto, boolean isSave) {
        // 获取当前人的id和部门id
        UserVO user = ThreadLocalUserUtil.get();

        // 业务数据
        MiniCustomerEditFlow temp = new MiniCustomerEditFlow();
        BeanUtils.copyProperties(dto, temp);

        // 设置流程字段，flow_type请自行对应“dict_flow_type”表中的id， 比如当前入职流程（考察登记流程）的id是5
        String flow_title = dto.getName() + "信息修改"; // 审批流程的名称，需要根据实际业务自行确定
        FlowBusinessDataSuperEntity fbdse = WorkFlowUtil.getStartSuperDataEntity(
                user.getId(),  // 当前用户id
                user.getMain_department_id(), // 提交的部门id
                22, // 流程类型id，“dict_flow_type”表中的id
                flow_title // 自定义的流程标题
        );
        BeanUtils.copyProperties(fbdse, temp);

        // 是否为新数据
        // 新数据时，前端不传业务数据id
        // 非新数据时，即来源是“草稿箱”、“已删除”、“被退回”时，前端需要传入业务数据id
        boolean isFirst = (dto.getId() == null);

        // 由于流程字段含有id，会覆盖数据，此处需要手动setId
        if (!isFirst) temp.setId(dto.getId());

        // 新增或更新业务数据
        boolean flag = (isFirst ? save(temp) : updateById(temp));
        if (!flag) throw new CommonException("保存失败");
        miniCustomerEditFunnelTmpService.remove(Wrappers.<MiniCustomerEditFunnelTmp>lambdaQuery().eq(MiniCustomerEditFunnelTmp::getMini_customer_edit_flow_id, temp.getId()));
        miniCustomerEditSelectionReasonTmpService.remove(Wrappers.<MiniCustomerEditSelectionReasonTmp>lambdaQuery().eq(MiniCustomerEditSelectionReasonTmp::getMini_customer_edit_flow_id, temp.getId()));
        // 保存子表数据
        miniCustomerEditFunnelTmpService.saveBatch(dto.getFunnels().stream().map(item -> {
            MiniCustomerEditFunnelTmp miniCustomerEditFunnelTmp = new MiniCustomerEditFunnelTmp();
            miniCustomerEditFunnelTmp.setMini_customer_edit_flow_id(temp.getId());
            miniCustomerEditFunnelTmp.setFunnel_type_id(item);
            return miniCustomerEditFunnelTmp;
        }).collect(Collectors.toList()));
        miniCustomerEditSelectionReasonTmpService.saveBatch(dto.getSelection_reasons().stream().map(item -> {
            MiniCustomerEditSelectionReasonTmp miniCustomerEditSelectionReasonTmp = new MiniCustomerEditSelectionReasonTmp();
            miniCustomerEditSelectionReasonTmp.setMini_customer_edit_flow_id(temp.getId());
            miniCustomerEditSelectionReasonTmp.setSelection_reason_id(item);
            return miniCustomerEditSelectionReasonTmp;
        }).collect(Collectors.toList()));
        // 构造流程工具类
        WorkFlowUtil wfu = new WorkFlowUtil<MiniCustomerEditFlow, MiniCustomerEditFlowMapper>(temp.getId(), user.getId(), MiniCustomerEditFlow.class);

        // 审批流程id
        // 新数据,传0L
        // 非新数据,根据数据id,查找wfData_id
        Long wfData_id = isFirst ? 0L : wfu.getWfDataId(dto.getId());
        // 旧数据记录留存
        MiniCustomerEditFlow old_data = isFirst ? new MiniCustomerEditFlow() : temp;

        return isSave ? wfu.SaveDraft(wfData_id) : wfu.Begin(wfData_id, "", old_data);
    }

    // 通过 和 驳回 抽出相同代码
    private int passAndBack(WorkFlowExtraCheckDTO dto, boolean isPass) {
        // 当前人id
        Long userId = ThreadLocalUserUtil.get().getId();

        // 业务数据
        MiniCustomerEditFlow temp = getById(dto.getId());

        // 构造流程工具类
        WorkFlowUtil wfu = new WorkFlowUtil<MiniCustomerEditFlow, MiniCustomerEditFlowMapper>(dto.getId(), userId, MiniCustomerEditFlow.class);

        // 审批入参类
        WorkFlowCheckDTO checkDTO = WorkFlowCheckDTO.getWorkFlowCheckDTO(
                temp.getFlow_current_node_id(), // 当前节点id
                temp.getFlow_json(), // 流程json
                dto.getWf_check_opinion(), // 审批意见
                dto.getWf_check_sign_url(), // 审批签名链接
                JSONObject.toJSONString(temp) // 旧数据留存
        );

        // 审批
        return isPass ? wfu.ToNext(checkDTO) : wfu.ReturnBack(checkDTO);
    }

    // 删除 和 彻底删除 抽出相同代码
    private int deleteAndActualDel(Long id, boolean isActual) {
        // 当前人id
        Long userId = ThreadLocalUserUtil.get().getId();

        // 构造流程工具类
        WorkFlowUtil wfu = new WorkFlowUtil<MiniCustomerEditFlow, MiniCustomerEditFlowMapper>(id, userId, MiniCustomerEditFlow.class);

        // 流程id
        Long wfData_id = wfu.getWfDataId(id);

        return isActual ? wfu.ActualDelete(wfData_id) : wfu.Delete(wfData_id);
    }
}
